#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
GitHub软件包检索工具
用于查找GitHub releases中的deb、appimage和linux tar包
"""

import requests
import json
import csv
import time
import logging
import os
import pickle
import argparse
from typing import List, Dict, Optional
from urllib.parse import urljoin
import re
from datetime import datetime, timedelta

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('github_package_finder.log', encoding='utf-8'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

class APIRateLimiter:
    """GitHub API限制处理器"""
    
    def __init__(self, github_token: Optional[str] = None):
        self.github_token = github_token
        self.requests_made = 0
        self.reset_time = None
        self.remaining_requests = None
        
        # 根据是否有token设置不同的限制
        if github_token:
            self.hourly_limit = 5000  # 认证用户
            self.requests_per_minute = 30
        else:
            self.hourly_limit = 60    # 未认证用户
            self.requests_per_minute = 10
    
    def check_rate_limit(self, response: requests.Response):
        """检查API限制状态"""
        if 'X-RateLimit-Remaining' in response.headers:
            self.remaining_requests = int(response.headers['X-RateLimit-Remaining'])
        
        if 'X-RateLimit-Reset' in response.headers:
            reset_timestamp = int(response.headers['X-RateLimit-Reset'])
            self.reset_time = datetime.fromtimestamp(reset_timestamp)
        
        logger.info(f"API限制状态: 剩余请求 {self.remaining_requests}, 重置时间 {self.reset_time}")
    
    def should_wait(self) -> bool:
        """判断是否需要等待"""
        if self.remaining_requests is None:
            return False
        
        # 如果剩余请求很少，需要等待
        if self.remaining_requests < 5:
            return True
        
        return False
    
    def get_wait_time(self) -> int:
        """获取需要等待的时间（秒）"""
        if self.reset_time and self.remaining_requests is not None:
            if self.remaining_requests < 5:
                # 等待到重置时间
                wait_seconds = (self.reset_time - datetime.now()).total_seconds()
                return max(60, int(wait_seconds))  # 至少等待1分钟
        
        # 默认等待时间
        return 60 if not self.github_token else 2
    
    def wait_if_needed(self):
        """如果需要，则等待"""
        if self.should_wait():
            wait_time = self.get_wait_time()
            logger.warning(f"API限制接近，等待 {wait_time} 秒...")
            time.sleep(wait_time)
        else:
            # 正常延迟
            time.sleep(2 if self.github_token else 5)

class ProgressManager:
    """进度管理器，支持断点续传"""
    
    def __init__(self, progress_file: str = "search_progress.pkl"):
        self.progress_file = progress_file
        self.progress = {
            'deb_packages': [],
            'appimage_packages': [],
            'tar_packages': [],
            'linux_packages': [],  # 新增：统一Linux包搜索
            'comprehensive_packages': [],  # 新增：全面搜索包
            'checked_repositories': [],  # 新增：所有检查过的仓库
            'completed_searches': {
                'deb': False,
                'appimage': False,
                'tar': False,
                'linux': False,  # 新增：统一Linux包搜索
                'comprehensive': False  # 新增：全面搜索策略
            },
            'current_search': None,
            'current_repo_index': 0,
            'start_time': None,
            'last_save_time': None
        }
        self.load_progress()
    
    def load_progress(self):
        """加载进度"""
        if os.path.exists(self.progress_file):
            try:
                with open(self.progress_file, 'rb') as f:
                    self.progress = pickle.load(f)
                logger.info(f"✅ 加载进度文件: {self.progress_file}")
                self._print_progress_summary()
            except Exception as e:
                logger.warning(f"⚠️ 加载进度文件失败: {e}")
                self.progress = self._get_default_progress()
        else:
            logger.info("🆕 开始新的搜索任务")
            self.progress = self._get_default_progress()
    
    def _get_default_progress(self):
        """获取默认进度"""
        return {
            'deb_packages': [],
            'appimage_packages': [],
            'tar_packages': [],
            'linux_packages': [],  # 新增：统一Linux包搜索
            'comprehensive_packages': [],  # 新增：全面搜索包
            'checked_repositories': [],  # 新增：所有检查过的仓库
            'completed_searches': {
                'deb': False,
                'appimage': False,
                'tar': False,
                'linux': False,  # 新增：统一Linux包搜索
                'comprehensive': False  # 新增：全面搜索策略
            },
            'current_search': None,
            'current_repo_index': 0,
            'start_time': datetime.now().isoformat(),
            'last_save_time': None
        }
    
    def save_progress(self):
        """保存进度"""
        try:
            self.progress['last_save_time'] = datetime.now().isoformat()
            with open(self.progress_file, 'wb') as f:
                pickle.dump(self.progress, f)
            logger.info(f"💾 进度已保存: {self.progress_file}")
        except Exception as e:
            logger.error(f"❌ 保存进度失败: {e}")
    
    def start_search(self, search_type: str):
        """开始新的搜索类型"""
        self.progress['current_search'] = search_type
        self.progress['current_repo_index'] = 0
        logger.info(f"🚀 开始搜索: {search_type}")
    
    def update_repo_index(self, index: int):
        """更新当前仓库索引"""
        self.progress['current_repo_index'] = index
    
    def add_packages(self, search_type: str, packages: List[Dict]):
        """添加找到的包"""
        if search_type == 'deb':
            self.progress['deb_packages'].extend(packages)
        elif search_type == 'appimage':
            self.progress['appimage_packages'].extend(packages)
        elif search_type == 'tar':
            self.progress['tar_packages'].extend(packages)
        elif search_type == 'linux':
            self.progress['linux_packages'].extend(packages)
        elif search_type == 'comprehensive':
            self.progress['comprehensive_packages'].extend(packages)
    
    def complete_search(self, search_type: str):
        """标记搜索完成"""
        self.progress['completed_searches'][search_type] = True
        logger.info(f"✅ 完成搜索: {search_type}")
    
    def is_search_completed(self, search_type: str) -> bool:
        """检查搜索是否已完成"""
        return self.progress['completed_searches'].get(search_type, False)
    
    def get_packages(self, search_type: str) -> List[Dict]:
        """获取已找到的包"""
        if search_type == 'deb':
            return self.progress['deb_packages']
        elif search_type == 'appimage':
            return self.progress['appimage_packages']
        elif search_type == 'tar':
            return self.progress['tar_packages']
        elif search_type == 'linux':
            return self.progress['linux_packages']
        elif search_type == 'comprehensive':
            return self.progress['comprehensive_packages']
        return []
    
    def get_current_repo_index(self) -> int:
        """获取当前仓库索引"""
        return self.progress.get('current_repo_index', 0)
    
    def add_checked_repository(self, repo_info: Dict):
        """添加检查过的仓库信息"""
        self.progress['checked_repositories'].append(repo_info)
    
    def get_checked_repositories(self) -> List[Dict]:
        """获取所有检查过的仓库"""
        return self.progress['checked_repositories']
    
    def _print_progress_summary(self):
        """打印进度摘要"""
        logger.info("📊 进度摘要:")
        logger.info(f"  - Deb包: {len(self.progress['deb_packages'])} 个")
        logger.info(f"  - AppImage包: {len(self.progress['appimage_packages'])} 个")
        logger.info(f"  - Tar包: {len(self.progress['tar_packages'])} 个")
        logger.info(f"  - Linux包: {len(self.progress['linux_packages'])} 个")
        logger.info(f"  - 全面搜索包: {len(self.progress['comprehensive_packages'])} 个")
        logger.info(f"  - 检查过的仓库: {len(self.progress['checked_repositories'])} 个")
        
        completed = []
        for search_type, is_completed in self.progress['completed_searches'].items():
            if is_completed:
                completed.append(search_type)
        
        if completed:
            logger.info(f"  - 已完成: {', '.join(completed)}")
        
        if self.progress.get('current_search'):
            logger.info(f"  - 当前搜索: {self.progress['current_search']}")
            logger.info(f"  - 当前索引: {self.progress['current_repo_index']}")
    
    def clear_progress(self):
        """清除进度"""
        if os.path.exists(self.progress_file):
            os.remove(self.progress_file)
        self.progress = self._get_default_progress()
        logger.info("🗑️ 进度已清除")

class GitHubPackageFinder:
    def __init__(self, github_token: Optional[str] = None, progress_file: str = "search_progress.pkl"):
        """
        初始化GitHub包查找器
        
        Args:
            github_token: GitHub API token，用于提高请求限制
            progress_file: 进度文件路径
        """
        self.github_token = github_token
        self.rate_limiter = APIRateLimiter(github_token)
        self.progress_manager = ProgressManager(progress_file)
        self.session = requests.Session()
        if github_token:
            self.session.headers.update({
                'Authorization': f'token {github_token}',
                'Accept': 'application/vnd.github.v3+json'
            })
        else:
            self.session.headers.update({
                'Accept': 'application/vnd.github.v3+json'
            })
        
        self.base_url = 'https://api.github.com'
        self.results = []
        
    def search_repositories(self, query: str, per_page: int = 100) -> List[Dict]:
        """
        搜索GitHub仓库，按星数降序排列
        
        Args:
            query: 搜索查询字符串
            per_page: 每页结果数量
            
        Returns:
            按星数排序的仓库列表
        """
        url = f"{self.base_url}/search/repositories"
        params = {
            'q': query,
            'sort': 'stars',
            'order': 'desc',
            'per_page': per_page
        }
        
        try:
            # 检查是否需要等待
            self.rate_limiter.wait_if_needed()
            
            response = self.session.get(url, params=params)
            response.raise_for_status()
            
            # 检查API限制状态
            self.rate_limiter.check_rate_limit(response)
            
            data = response.json()
            repos = data.get('items', [])
            
            # 确保按星数排序（虽然API已经排序，但这里再次确认）
            repos.sort(key=lambda x: x.get('stargazers_count', 0), reverse=True)
            
            logger.info(f"搜索 '{query}' 找到 {len(repos)} 个仓库，按星数排序")
            if repos:
                logger.info(f"最高星数: {repos[0].get('stargazers_count', 0)} ({repos[0]['full_name']})")
            
            return repos
        except requests.exceptions.RequestException as e:
            logger.error(f"搜索仓库时出错: {e}")
            return []
    
    def get_trending_repositories(self, language: str = None, since: str = 'daily', per_page: int = 100) -> List[Dict]:
        """
        获取GitHub趋势仓库
        
        Args:
            language: 编程语言过滤
            since: 时间范围 (daily, weekly, monthly)
            per_page: 每页结果数量
            
        Returns:
            趋势仓库列表
        """
        # 注意：GitHub API没有直接的trending接口，这里使用搜索API模拟
        # 通过搜索最近更新的仓库来获取趋势
        query_parts = ['created:>2024-01-01']  # 最近创建的仓库
        
        if language:
            query_parts.append(f'language:{language}')
        
        query = ' '.join(query_parts)
        return self.search_repositories(query, per_page)
    
    def get_popular_repositories_by_language(self, languages: List[str], per_page: int = 50) -> List[Dict]:
        """
        按编程语言获取热门仓库
        
        Args:
            languages: 编程语言列表
            per_page: 每种语言获取的仓库数量
            
        Returns:
            热门仓库列表
        """
        all_repos = []
        
        for language in languages:
            logger.info(f"获取 {language} 语言的热门仓库...")
            query = f'language:{language}'
            repos = self.search_repositories(query, per_page)
            all_repos.extend(repos)
            
            # 避免API限制
            time.sleep(1)
        
        # 去重并按星数排序
        seen = set()
        unique_repos = []
        for repo in all_repos:
            repo_id = repo['id']
            if repo_id not in seen:
                seen.add(repo_id)
                unique_repos.append(repo)
        
        unique_repos.sort(key=lambda x: x.get('stargazers_count', 0), reverse=True)
        return unique_repos
    
    def get_repositories_by_stars_range(self, min_stars: int = 1000, max_stars: int = 100000, per_page: int = 100) -> List[Dict]:
        """
        按星数范围获取仓库
        
        Args:
            min_stars: 最小星数
            max_stars: 最大星数
            per_page: 每页结果数量
            
        Returns:
            仓库列表
        """
        query = f'stars:{min_stars}..{max_stars}'
        return self.search_repositories(query, per_page)
    
    def get_repositories_by_organization(self, orgs: List[str], per_page: int = 50) -> List[Dict]:
        """
        获取特定组织的仓库
        
        Args:
            orgs: 组织名称列表
            per_page: 每个组织获取的仓库数量
            
        Returns:
            仓库列表
        """
        all_repos = []
        
        for org in orgs:
            logger.info(f"获取组织 {org} 的仓库...")
            query = f'org:{org}'
            repos = self.search_repositories(query, per_page)
            all_repos.extend(repos)
            
            # 避免API限制
            time.sleep(1)
        
        return all_repos
    
    def get_repositories_by_topic(self, topics: List[str], per_page: int = 50) -> List[Dict]:
        """
        按主题搜索仓库
        
        Args:
            topics: 主题列表
            per_page: 每个主题获取的仓库数量
            
        Returns:
            仓库列表
        """
        all_repos = []
        
        for topic in topics:
            logger.info(f"搜索主题: {topic}")
            query = f'topic:{topic}'
            repos = self.search_repositories(query, per_page)
            all_repos.extend(repos)
            
            # 避免API限制
            time.sleep(1)
        
        # 去重并按星数排序
        seen = set()
        unique_repos = []
        for repo in all_repos:
            repo_id = repo['id']
            if repo_id not in seen:
                seen.add(repo_id)
                unique_repos.append(repo)
        
        unique_repos.sort(key=lambda x: x.get('stargazers_count', 0), reverse=True)
        return unique_repos
    
    def get_repository_releases(self, owner: str, repo: str) -> List[Dict]:
        """
        获取仓库的releases
        
        Args:
            owner: 仓库所有者
            repo: 仓库名称
            
        Returns:
            releases列表
        """
        url = f"{self.base_url}/repos/{owner}/{repo}/releases"
        
        try:
            # 检查是否需要等待
            self.rate_limiter.wait_if_needed()
            
            response = self.session.get(url)
            response.raise_for_status()
            
            # 检查API限制状态
            self.rate_limiter.check_rate_limit(response)
            
            return response.json()
        except requests.exceptions.RequestException as e:
            logger.error(f"获取 {owner}/{repo} 的releases时出错: {e}")
            return []
    
    def find_packages_in_release(self, release: Dict, package_types: List[str]) -> List[Dict]:
        """
        在release中查找指定类型的包
        
        Args:
            release: release信息
            package_types: 包类型列表 ['deb', 'appimage', 'tar']
            
        Returns:
            找到的包信息列表
        """
        found_packages = []
        assets = release.get('assets', [])
        
        for asset in assets:
            name = asset.get('name', '').lower()
            download_url = asset.get('browser_download_url', '')
            
            for package_type in package_types:
                if self._is_package_type(name, package_type):
                    found_packages.append({
                        'package_name': asset.get('name', ''),
                        'package_type': package_type,
                        'download_url': download_url,
                        'size': asset.get('size', 0),
                        'release_tag': release.get('tag_name', ''),
                        'release_name': release.get('name', ''),
                        'published_at': release.get('published_at', ''),
                        'release_url': release.get('html_url', '')
                    })
                    break
        
        return found_packages
    
    def _is_package_type(self, filename: str, package_type: str) -> bool:
        """
        判断文件名是否为指定类型的包
        
        Args:
            filename: 文件名
            package_type: 包类型
            
        Returns:
            是否为指定类型
        """
        if package_type == 'deb':
            return filename.endswith('.deb')
        elif package_type == 'appimage':
            return filename.endswith('.appimage') or 'appimage' in filename
        elif package_type == 'tar':
            # 查找linux相关的tar包
            return (filename.endswith('.tar.gz') or 
                   filename.endswith('.tar.bz2') or 
                   filename.endswith('.tar.xz') or
                   filename.endswith('.tar')) and (
                   'linux' in filename or 
                   'ubuntu' in filename or 
                   'debian' in filename or
                   'x86_64' in filename or
                   'amd64' in filename or
                   'i386' in filename or
                   'i686' in filename)
        return False
    
    def _check_linux_support(self, repo: Dict) -> bool:
        """
        检查仓库是否支持Linux系统
        
        Args:
            repo: 仓库信息
            
        Returns:
            是否支持Linux
        """
        # 检查仓库描述和主题
        description = repo.get('description', '').lower()
        topics = [topic.lower() for topic in repo.get('topics', [])]
        
        # Linux相关关键词
        linux_keywords = [
            'linux', 'ubuntu', 'debian', 'fedora', 'centos', 'arch',
            'cross-platform', 'multi-platform', 'portable', 'universal'
        ]
        
        # 检查描述中是否包含Linux关键词
        for keyword in linux_keywords:
            if keyword in description:
                return True
        
        # 检查主题中是否包含Linux关键词
        for keyword in linux_keywords:
            if keyword in topics:
                return True
        
        # 检查语言（某些语言通常支持跨平台）
        language = repo.get('language', '')
        if language:
            language = language.lower()
            cross_platform_languages = [
                'python', 'javascript', 'typescript', 'go', 'rust', 'java',
                'c++', 'c', 'kotlin', 'dart', 'swift'
            ]
            
            if language in cross_platform_languages:
                return True
        
        return False
    
    def _find_packages_in_releases(self, releases: List[Dict], package_priority: List[str]) -> List[Dict]:
        """
        在releases中按优先级查找包
        
        Args:
            releases: releases列表
            package_priority: 包类型优先级列表 ['deb', 'appimage', 'tar']
            
        Returns:
            找到的包列表（按优先级排序）
        """
        found_packages = []
        
        for release in releases:
            assets = release.get('assets', [])
            
            # 按优先级检查包类型
            for package_type in package_priority:
                for asset in assets:
                    name = asset.get('name', '').lower()
                    download_url = asset.get('browser_download_url', '')
                    
                    if self._is_package_type(name, package_type):
                        found_packages.append({
                            'package_name': asset.get('name', ''),
                            'package_type': package_type,
                            'download_url': download_url,
                            'size': asset.get('size', 0),
                            'release_tag': release.get('tag_name', ''),
                            'release_name': release.get('name', ''),
                            'published_at': release.get('published_at', ''),
                            'release_url': release.get('html_url', '')
                        })
                        # 找到第一个匹配的包类型就停止（按优先级）
                        break
                
                # 如果找到了包，就不再检查其他类型
                if found_packages:
                    break
            
            # 如果找到了包，就不再检查其他release
            if found_packages:
                break
        
        return found_packages
    
    def search_linux_packages(self, max_repos: int = 50) -> List[Dict]:
        """
        按新策略搜索Linux包：先检查Linux支持，再按优先级检查包类型
        
        Args:
            max_repos: 最大搜索仓库数量
            
        Returns:
            找到的包列表
        """
        # 检查是否已完成
        if self.progress_manager.is_search_completed('linux'):
            logger.info("✅ Linux包搜索已完成，跳过")
            return self.progress_manager.get_packages('linux')
        
        logger.info("开始搜索Linux包（新策略：先检查Linux支持，再按优先级检查包）...")
        self.progress_manager.start_search('linux')
        all_packages = self.progress_manager.get_packages('linux')
        
        # 搜索策略：先找支持Linux的仓库
        queries = [
            'linux', 'ubuntu', 'debian', 'cross-platform', 'multi-platform',
            'portable', 'universal', 'desktop', 'gui', 'application'
        ]
        
        for query in queries:
            logger.info(f"搜索查询: {query}")
            repos = self.search_repositories(query, per_page=min(max_repos, 100))
            
            start_index = self.progress_manager.get_current_repo_index()
            for i, repo in enumerate(repos[:max_repos]):
                # 跳过已处理的仓库
                if i < start_index:
                    continue
                
                owner = repo['owner']['login']
                repo_name = repo['name']
                repo_url = repo['html_url']
                stars = repo.get('stargazers_count', 0)
                
                language = repo.get('language', 'Unknown')
                forks = repo.get('forks_count', 0)
                
                # 记录仓库信息（无论是否支持Linux）
                repo_info = {
                    'repository': f"{owner}/{repo_name}",
                    'repository_url': repo_url,
                    'stars': stars,
                    'forks': repo.get('forks_count', 0),
                    'language': repo.get('language', ''),
                    'created_at': repo.get('created_at', ''),
                    'updated_at': repo.get('updated_at', ''),
                    'description': repo.get('description', ''),
                    'license': repo.get('license', {}).get('name', '') if repo.get('license') else '',
                    'topics': ', '.join(repo.get('topics', [])),
                    'open_issues': repo.get('open_issues_count', 0),
                    'linux_support': False,
                    'has_packages': False,
                    'package_types': '',
                    'package_count': 0
                }
                
                # 检查是否支持Linux
                linux_support = self._check_linux_support(repo)
                repo_info['linux_support'] = linux_support
                
                if not linux_support:
                    logger.info(f"[{i+1}/{min(len(repos), max_repos)}] 跳过仓库: {owner}/{repo_name} (⭐ {stars} 🍴 {forks} 💻 {language}) - 不支持Linux")
                    self.progress_manager.add_checked_repository(repo_info)
                    continue
                
                logger.info(f"[{i+1}/{min(len(repos), max_repos)}] 检查仓库: {owner}/{repo_name} (⭐ {stars} 🍴 {forks} 💻 {language}) - 支持Linux")
                
            releases = self.get_repository_releases(owner, repo_name)
            if not releases:
                logger.info(f"  - 无releases，跳过")
                self.progress_manager.add_checked_repository(repo_info)
                # 实时保存仓库信息
                self.save_repositories_to_csv('github_repositories_realtime_linux.csv', append=True)
                continue
            
            # 按优先级查找包：deb > appimage > tar
            package_priority = ['deb', 'appimage', 'tar']
            found_packages = self._find_packages_in_releases(releases, package_priority)
                
            if found_packages:
                # 更新仓库信息
                repo_info['has_packages'] = True
                repo_info['package_types'] = ', '.join([p['package_type'] for p in found_packages])
                repo_info['package_count'] = len(found_packages)
                
                # 添加仓库信息到包
                for package in found_packages:
                    package.update({
                        'repository': f"{owner}/{repo_name}",
                        'repository_url': repo_url,
                        'stars': stars,
                        'forks': repo.get('forks_count', 0),
                        'language': repo.get('language', ''),
                        'created_at': repo.get('created_at', ''),
                        'updated_at': repo.get('updated_at', ''),
                        'description': repo.get('description', ''),
                        'license': repo.get('license', {}).get('name', '') if repo.get('license') else '',
                        'topics': ', '.join(repo.get('topics', [])),
                        'open_issues': repo.get('open_issues_count', 0)
                    })
                
                logger.info(f"  - 找到 {len(found_packages)} 个包: {[p['package_type'] for p in found_packages]}")
                all_packages.extend(found_packages)
                
                # 实时保存找到的包
                self.save_to_csv(found_packages, 'github_packages_realtime_linux.csv', append=True)
            else:
                logger.info(f"  - 未找到合适的包")
            
            # 记录检查过的仓库
            self.progress_manager.add_checked_repository(repo_info)
            
            # 实时保存仓库信息
            self.save_repositories_to_csv('github_repositories_realtime_linux.csv', append=True)
            
            # 更新进度
            self.progress_manager.update_repo_index(i + 1)
            self.progress_manager.add_packages('linux', found_packages)
            
            # 每处理5个仓库保存一次进度
            if (i + 1) % 5 == 0:
                self.progress_manager.save_progress()
        
        # 标记搜索完成
        self.progress_manager.complete_search('linux')
        self.progress_manager.save_progress()
        
        all_packages = self.progress_manager.get_packages('linux')
        logger.info(f"找到 {len(all_packages)} 个Linux包")
        
        # 按包类型统计
        package_stats = {}
        for package in all_packages:
            pkg_type = package.get('package_type', 'unknown')
            package_stats[pkg_type] = package_stats.get(pkg_type, 0) + 1
        
        logger.info("包类型统计:")
        for pkg_type, count in sorted(package_stats.items(), key=lambda x: x[1], reverse=True):
            logger.info(f"  - {pkg_type}: {count} 个")
        
        return all_packages
    
    def search_linux_packages_comprehensive(self, max_repos_per_strategy: int = 20) -> List[Dict]:
        """
        全面搜索Linux包：使用多种策略遍历GitHub仓库
        
        Args:
            max_repos_per_strategy: 每种策略最大搜索仓库数量
            
        Returns:
            找到的包列表
        """
        # 检查是否已完成
        if self.progress_manager.is_search_completed('comprehensive'):
            logger.info("✅ 全面Linux包搜索已完成，跳过")
            return self.progress_manager.get_packages('comprehensive')
        
        logger.info("开始全面搜索Linux包（多策略遍历GitHub仓库）...")
        self.progress_manager.start_search('comprehensive')
        all_packages = self.progress_manager.get_packages('comprehensive')
        
        # 策略1: 按编程语言搜索热门仓库
        logger.info("🔍 策略1: 按编程语言搜索热门仓库")
        popular_languages = [
            'Python', 'JavaScript', 'TypeScript', 'Go', 'Rust', 'C++', 'C', 
            'Java', 'C#', 'Kotlin', 'Swift', 'Dart', 'PHP', 'Ruby', 'Shell'
        ]
        
        repos_by_language = self.get_popular_repositories_by_language(
            popular_languages, per_page=max_repos_per_strategy
        )
        
        logger.info(f"按语言策略找到 {len(repos_by_language)} 个仓库")
        all_packages.extend(self._process_repositories(repos_by_language, "语言策略"))
        
        # 策略2: 按星数范围搜索
        logger.info("🔍 策略2: 按星数范围搜索")
        star_ranges = [
            (1000, 10000),    # 中等热门
            (10000, 50000),   # 很热门
            (50000, 200000),  # 超级热门
        ]
        
        for min_stars, max_stars in star_ranges:
            logger.info(f"搜索星数范围: {min_stars}-{max_stars}")
            repos_by_stars = self.get_repositories_by_stars_range(
                min_stars, max_stars, per_page=max_repos_per_strategy
            )
            all_packages.extend(self._process_repositories(repos_by_stars, f"星数{min_stars}-{max_stars}"))
        
        # 策略3: 搜索知名组织
        logger.info("🔍 策略3: 搜索知名组织")
        popular_orgs = [
            'microsoft', 'google', 'facebook', 'apple', 'netflix', 'uber',
            'airbnb', 'spotify', 'github', 'gitlab', 'canonical', 'redhat',
            'mozilla', 'apache', 'eclipse', 'kubernetes', 'docker', 'hashicorp'
        ]
        
        repos_by_org = self.get_repositories_by_organization(
            popular_orgs, per_page=max_repos_per_strategy
        )
        logger.info(f"按组织策略找到 {len(repos_by_org)} 个仓库")
        all_packages.extend(self._process_repositories(repos_by_org, "组织策略"))
        
        # 策略4: 搜索趋势仓库
        logger.info("🔍 策略4: 搜索趋势仓库")
        trending_languages = ['Python', 'JavaScript', 'Go', 'Rust', 'TypeScript']
        
        for language in trending_languages:
            logger.info(f"获取 {language} 趋势仓库")
            trending_repos = self.get_trending_repositories(
                language=language, per_page=max_repos_per_strategy
            )
            all_packages.extend(self._process_repositories(trending_repos, f"{language}趋势"))
        
        # 策略5: 按主题搜索
        logger.info("🔍 策略5: 按主题搜索")
        popular_topics = [
            'desktop', 'gui', 'application', 'tool', 'utility', 'client',
            'editor', 'browser', 'player', 'manager', 'viewer', 'reader',
            'terminal', 'shell', 'cli', 'command', 'system', 'os',
            'framework', 'library', 'sdk', 'api', 'service', 'server',
            'linux', 'ubuntu', 'debian', 'cross-platform', 'multi-platform',
            'portable', 'universal', 'download', 'file-manager', 'text-editor',
            'image-viewer', 'video-player', 'audio-player', 'pdf-reader',
            'office', 'productivity', 'development', 'ide', 'debugger'
        ]
        
        repos_by_topic = self.get_repositories_by_topic(
            popular_topics, per_page=max_repos_per_strategy
        )
        logger.info(f"按主题策略找到 {len(repos_by_topic)} 个仓库")
        all_packages.extend(self._process_repositories(repos_by_topic, "主题策略"))
        
        # 策略6: 扩展关键词搜索
        logger.info("🔍 策略6: 扩展关键词搜索")
        extended_keywords = [
            'desktop', 'gui', 'application', 'tool', 'utility', 'client',
            'editor', 'browser', 'player', 'manager', 'viewer', 'reader',
            'terminal', 'shell', 'cli', 'command', 'system', 'os',
            'framework', 'library', 'sdk', 'api', 'service', 'server'
        ]
        
        for keyword in extended_keywords:
            logger.info(f"搜索关键词: {keyword}")
            keyword_repos = self.search_repositories(keyword, per_page=max_repos_per_strategy)
            all_packages.extend(self._process_repositories(keyword_repos, f"关键词{keyword}"))
        
        # 去重
        seen_packages = set()
        unique_packages = []
        for package in all_packages:
            package_key = f"{package.get('repository', '')}_{package.get('package_name', '')}"
            if package_key not in seen_packages:
                seen_packages.add(package_key)
                unique_packages.append(package)
        
        # 标记搜索完成
        self.progress_manager.complete_search('comprehensive')
        self.progress_manager.save_progress()
        
        logger.info(f"全面搜索完成！总共找到 {len(unique_packages)} 个唯一Linux包")
        
        # 按包类型统计
        package_stats = {}
        for package in unique_packages:
            pkg_type = package.get('package_type', 'unknown')
            package_stats[pkg_type] = package_stats.get(pkg_type, 0) + 1
        
        logger.info("包类型统计:")
        for pkg_type, count in sorted(package_stats.items(), key=lambda x: x[1], reverse=True):
            logger.info(f"  - {pkg_type}: {count} 个")
        
        return unique_packages
    
    def search_linux_packages_by_topic(self, topics: List[str], max_repos_per_topic: int = 20) -> List[Dict]:
        """
        按主题搜索Linux包
        
        Args:
            topics: 主题列表
            max_repos_per_topic: 每个主题最大搜索仓库数量
            
        Returns:
            找到的包列表
        """
        # 检查是否已完成
        search_key = f"topic_{','.join(topics[:3])}"  # 使用前3个主题作为搜索标识
        if self.progress_manager.is_search_completed(search_key):
            logger.info(f"✅ 主题搜索已完成，跳过: {search_key}")
            return self.progress_manager.get_packages(search_key)
        
        logger.info(f"开始按主题搜索Linux包: {topics}")
        self.progress_manager.start_search(search_key)
        all_packages = self.progress_manager.get_packages(search_key)
        
        # 按主题搜索
        repos_by_topic = self.get_repositories_by_topic(topics, per_page=max_repos_per_topic)
        logger.info(f"按主题策略找到 {len(repos_by_topic)} 个仓库")
        
        found_packages = self._process_repositories(repos_by_topic, f"主题搜索-{','.join(topics[:3])}")
        all_packages.extend(found_packages)
        
        # 标记搜索完成
        self.progress_manager.complete_search(search_key)
        self.progress_manager.save_progress()
        
        logger.info(f"主题搜索完成！总共找到 {len(found_packages)} 个Linux包")
        
        # 按包类型统计
        package_stats = {}
        for package in found_packages:
            pkg_type = package.get('package_type', 'unknown')
            package_stats[pkg_type] = package_stats.get(pkg_type, 0) + 1
        
        logger.info("包类型统计:")
        for pkg_type, count in sorted(package_stats.items(), key=lambda x: x[1], reverse=True):
            logger.info(f"  - {pkg_type}: {count} 个")
        
        return found_packages
    
    def _process_repositories(self, repositories: List[Dict], strategy_name: str) -> List[Dict]:
        """
        处理仓库列表，查找包
        
        Args:
            repositories: 仓库列表
            strategy_name: 策略名称
            
        Returns:
            找到的包列表
        """
        found_packages = []
        
        for repo in repositories:
            owner = repo['owner']['login']
            repo_name = repo['name']
            repo_url = repo['html_url']
            stars = repo.get('stargazers_count', 0)
            
            language = repo.get('language', 'Unknown')
            forks = repo.get('forks_count', 0)
            
            # 记录仓库信息
            repo_info = {
                'repository': f"{owner}/{repo_name}",
                'repository_url': repo_url,
                'stars': stars,
                'forks': repo.get('forks_count', 0),
                'language': repo.get('language', ''),
                'created_at': repo.get('created_at', ''),
                'updated_at': repo.get('updated_at', ''),
                'description': repo.get('description', ''),
                'license': repo.get('license', {}).get('name', '') if repo.get('license') else '',
                'topics': ', '.join(repo.get('topics', [])),
                'open_issues': repo.get('open_issues_count', 0),
                'search_strategy': strategy_name,
                'linux_support': False,
                'has_packages': False,
                'package_types': '',
                'package_count': 0
            }
            
            # 检查是否支持Linux
            linux_support = self._check_linux_support(repo)
            repo_info['linux_support'] = linux_support
            
            if not linux_support:
                logger.info(f"[{strategy_name}] 跳过仓库: {owner}/{repo_name} (⭐ {stars}) - 不支持Linux")
                self.progress_manager.add_checked_repository(repo_info)
                continue
            
            logger.info(f"[{strategy_name}] 检查仓库: {owner}/{repo_name} (⭐ {stars} 🍴 {forks} 💻 {language}) - 支持Linux")
            
            releases = self.get_repository_releases(owner, repo_name)
            if not releases:
                logger.info(f"  - 无releases，跳过")
                self.progress_manager.add_checked_repository(repo_info)
                continue
            
            # 按优先级查找包：deb > appimage > tar
            package_priority = ['deb', 'appimage', 'tar']
            found_packages_in_repo = self._find_packages_in_releases(releases, package_priority)
            
            if found_packages_in_repo:
                # 更新仓库信息
                repo_info['has_packages'] = True
                repo_info['package_types'] = ', '.join([p['package_type'] for p in found_packages_in_repo])
                repo_info['package_count'] = len(found_packages_in_repo)
                
                # 添加仓库信息到包
                for package in found_packages_in_repo:
                    package.update({
                        'repository': f"{owner}/{repo_name}",
                        'repository_url': repo_url,
                        'stars': stars,
                        'forks': repo.get('forks_count', 0),
                        'language': repo.get('language', ''),
                        'created_at': repo.get('created_at', ''),
                        'updated_at': repo.get('updated_at', ''),
                        'description': repo.get('description', ''),
                        'license': repo.get('license', {}).get('name', '') if repo.get('license') else '',
                        'topics': ', '.join(repo.get('topics', [])),
                        'open_issues': repo.get('open_issues_count', 0),
                        'search_strategy': strategy_name
                    })
                
                logger.info(f"  - 找到 {len(found_packages_in_repo)} 个包: {[p['package_type'] for p in found_packages_in_repo]}")
                found_packages.extend(found_packages_in_repo)
                
                # 实时保存找到的包
                self.save_to_csv(found_packages_in_repo, f'github_packages_realtime_{strategy_name}.csv', append=True)
            else:
                logger.info(f"  - 未找到合适的包")
            
            # 记录检查过的仓库
            self.progress_manager.add_checked_repository(repo_info)
            
            # 实时保存仓库信息
            self.save_repositories_to_csv(f'github_repositories_realtime_{strategy_name}.csv', append=True)
        
        return found_packages
    
    def search_deb_packages(self, max_repos: int = 50) -> List[Dict]:
        """
        搜索包含deb包的仓库，支持断点续传
        
        Args:
            max_repos: 最大搜索仓库数量
            
        Returns:
            找到的deb包列表
        """
        # 检查是否已完成
        if self.progress_manager.is_search_completed('deb'):
            logger.info("✅ Deb包搜索已完成，跳过")
            return self.progress_manager.get_packages('deb')
        
        logger.info("开始搜索deb包...")
        self.progress_manager.start_search('deb')
        deb_packages = self.progress_manager.get_packages('deb')
        
        # 搜索包含deb包的仓库
        queries = [
            'filename:*.deb',
            'deb package',
            'debian package'
        ]
        
        for query in queries:
            logger.info(f"搜索查询: {query}")
            repos = self.search_repositories(query, per_page=min(max_repos, 100))
            
            start_index = self.progress_manager.get_current_repo_index()
            for i, repo in enumerate(repos[:max_repos]):
                # 跳过已处理的仓库
                if i < start_index:
                    continue
                
                owner = repo['owner']['login']
                repo_name = repo['name']
                repo_url = repo['html_url']
                stars = repo.get('stargazers_count', 0)
                
                language = repo.get('language', 'Unknown')
                forks = repo.get('forks_count', 0)
                logger.info(f"[{i+1}/{min(len(repos), max_repos)}] 检查仓库: {owner}/{repo_name} (⭐ {stars} 🍴 {forks} 💻 {language})")
                
                # 记录仓库信息
                repo_info = {
                    'repository': f"{owner}/{repo_name}",
                    'repository_url': repo_url,
                    'stars': stars,
                    'forks': repo.get('forks_count', 0),
                    'language': repo.get('language', ''),
                    'created_at': repo.get('created_at', ''),
                    'updated_at': repo.get('updated_at', ''),
                    'description': repo.get('description', ''),
                    'license': repo.get('license', {}).get('name', '') if repo.get('license') else '',
                    'topics': ', '.join(repo.get('topics', [])),
                    'open_issues': repo.get('open_issues_count', 0),
                    'search_type': 'deb',
                    'has_packages': False,
                    'package_types': '',
                    'package_count': 0
                }
                
                releases = self.get_repository_releases(owner, repo_name)
                found_packages = []
                for release in releases:
                    packages = self.find_packages_in_release(release, ['deb'])
                    for package in packages:
                        package.update({
                            'repository': f"{owner}/{repo_name}",
                            'repository_url': repo_url,
                            'stars': stars,
                            'forks': repo.get('forks_count', 0),
                            'language': repo.get('language', ''),
                            'created_at': repo.get('created_at', ''),
                            'updated_at': repo.get('updated_at', ''),
                            'description': repo.get('description', ''),
                            'license': repo.get('license', {}).get('name', '') if repo.get('license') else '',
                            'topics': ', '.join(repo.get('topics', [])),
                            'open_issues': repo.get('open_issues_count', 0)
                        })
                        found_packages.append(package)
                
                # 更新仓库信息
                if found_packages:
                    repo_info['has_packages'] = True
                    repo_info['package_types'] = 'deb'
                    repo_info['package_count'] = len(found_packages)
                
                # 记录检查过的仓库
                self.progress_manager.add_checked_repository(repo_info)
                
                # 更新进度
                self.progress_manager.update_repo_index(i + 1)
                self.progress_manager.add_packages('deb', found_packages)
                
                # 每处理5个仓库保存一次进度
                if (i + 1) % 5 == 0:
                    self.progress_manager.save_progress()
        
        # 标记搜索完成
        self.progress_manager.complete_search('deb')
        self.progress_manager.save_progress()
        
        deb_packages = self.progress_manager.get_packages('deb')
        logger.info(f"找到 {len(deb_packages)} 个deb包")
        return deb_packages
    
    def search_appimage_packages(self, max_repos: int = 50) -> List[Dict]:
        """
        搜索包含appimage包的仓库，支持断点续传
        
        Args:
            max_repos: 最大搜索仓库数量
            
        Returns:
            找到的appimage包列表
        """
        # 检查是否已完成
        if self.progress_manager.is_search_completed('appimage'):
            logger.info("✅ AppImage包搜索已完成，跳过")
            return self.progress_manager.get_packages('appimage')
        
        logger.info("开始搜索appimage包...")
        self.progress_manager.start_search('appimage')
        appimage_packages = self.progress_manager.get_packages('appimage')
        
        # 搜索包含appimage包的仓库
        queries = [
            'filename:*.appimage',
            'appimage',
            'AppImage'
        ]
        
        for query in queries:
            logger.info(f"搜索查询: {query}")
            repos = self.search_repositories(query, per_page=min(max_repos, 100))
            
            start_index = self.progress_manager.get_current_repo_index()
            for i, repo in enumerate(repos[:max_repos]):
                # 跳过已处理的仓库
                if i < start_index:
                    continue
                
                owner = repo['owner']['login']
                repo_name = repo['name']
                repo_url = repo['html_url']
                stars = repo.get('stargazers_count', 0)
                
                language = repo.get('language', 'Unknown')
                forks = repo.get('forks_count', 0)
                logger.info(f"[{i+1}/{min(len(repos), max_repos)}] 检查仓库: {owner}/{repo_name} (⭐ {stars} 🍴 {forks} 💻 {language})")
                
                releases = self.get_repository_releases(owner, repo_name)
                found_packages = []
                for release in releases:
                    packages = self.find_packages_in_release(release, ['appimage'])
                    for package in packages:
                        package.update({
                            'repository': f"{owner}/{repo_name}",
                            'repository_url': repo_url,
                            'stars': stars,
                            'forks': repo.get('forks_count', 0),
                            'language': repo.get('language', ''),
                            'created_at': repo.get('created_at', ''),
                            'updated_at': repo.get('updated_at', ''),
                            'description': repo.get('description', ''),
                            'license': repo.get('license', {}).get('name', '') if repo.get('license') else '',
                            'topics': ', '.join(repo.get('topics', [])),
                            'open_issues': repo.get('open_issues_count', 0)
                        })
                        found_packages.append(package)
                
                # 更新进度
                self.progress_manager.update_repo_index(i + 1)
                self.progress_manager.add_packages('appimage', found_packages)
                
                # 每处理5个仓库保存一次进度
                if (i + 1) % 5 == 0:
                    self.progress_manager.save_progress()
        
        # 标记搜索完成
        self.progress_manager.complete_search('appimage')
        self.progress_manager.save_progress()
        
        appimage_packages = self.progress_manager.get_packages('appimage')
        logger.info(f"找到 {len(appimage_packages)} 个appimage包")
        return appimage_packages
    
    def search_linux_tar_packages(self, max_repos: int = 50) -> List[Dict]:
        """
        搜索包含linux tar包的仓库，支持断点续传
        
        Args:
            max_repos: 最大搜索仓库数量
            
        Returns:
            找到的linux tar包列表
        """
        # 检查是否已完成
        if self.progress_manager.is_search_completed('tar'):
            logger.info("✅ Linux Tar包搜索已完成，跳过")
            return self.progress_manager.get_packages('tar')
        
        logger.info("开始搜索linux tar包...")
        self.progress_manager.start_search('tar')
        tar_packages = self.progress_manager.get_packages('tar')
        
        # 搜索包含linux tar包的仓库
        queries = [
            'filename:*.tar.gz linux',
            'filename:*.tar.bz2 linux',
            'linux binary',
            'linux release'
        ]
        
        for query in queries:
            logger.info(f"搜索查询: {query}")
            repos = self.search_repositories(query, per_page=min(max_repos, 100))
            
            start_index = self.progress_manager.get_current_repo_index()
            for i, repo in enumerate(repos[:max_repos]):
                # 跳过已处理的仓库
                if i < start_index:
                    continue
                
                owner = repo['owner']['login']
                repo_name = repo['name']
                repo_url = repo['html_url']
                stars = repo.get('stargazers_count', 0)
                
                language = repo.get('language', 'Unknown')
                forks = repo.get('forks_count', 0)
                logger.info(f"[{i+1}/{min(len(repos), max_repos)}] 检查仓库: {owner}/{repo_name} (⭐ {stars} 🍴 {forks} 💻 {language})")
                
                releases = self.get_repository_releases(owner, repo_name)
                found_packages = []
                for release in releases:
                    packages = self.find_packages_in_release(release, ['tar'])
                    for package in packages:
                        package.update({
                            'repository': f"{owner}/{repo_name}",
                            'repository_url': repo_url,
                            'stars': stars,
                            'forks': repo.get('forks_count', 0),
                            'language': repo.get('language', ''),
                            'created_at': repo.get('created_at', ''),
                            'updated_at': repo.get('updated_at', ''),
                            'description': repo.get('description', ''),
                            'license': repo.get('license', {}).get('name', '') if repo.get('license') else '',
                            'topics': ', '.join(repo.get('topics', [])),
                            'open_issues': repo.get('open_issues_count', 0)
                        })
                        found_packages.append(package)
                
                # 更新进度
                self.progress_manager.update_repo_index(i + 1)
                self.progress_manager.add_packages('tar', found_packages)
                
                # 每处理5个仓库保存一次进度
                if (i + 1) % 5 == 0:
                    self.progress_manager.save_progress()
        
        # 标记搜索完成
        self.progress_manager.complete_search('tar')
        self.progress_manager.save_progress()
        
        tar_packages = self.progress_manager.get_packages('tar')
        logger.info(f"找到 {len(tar_packages)} 个linux tar包")
        return tar_packages
    
    def save_to_csv(self, packages: List[Dict], filename: str, append: bool = False):
        """
        将包信息保存到CSV文件，按星数降序排列
        
        Args:
            packages: 包信息列表
            filename: 输出文件名
            append: 是否追加模式（用于实时保存）
        """
        if not packages:
            if not append:
                logger.warning("没有包信息可保存")
            return
        
        # 按星数降序排序
        packages.sort(key=lambda x: x.get('stars', 0), reverse=True)
        
        fieldnames = [
            'repository', 'repository_url', 'package_name', 'package_type',
            'download_url', 'release_tag', 'release_name', 'published_at',
            'release_url', 'stars', 'forks', 'language', 'created_at', 
            'updated_at', 'description', 'license', 'topics', 'open_issues', 'size'
        ]
        
        # 如果包中包含search_strategy字段，添加到fieldnames
        if packages and any('search_strategy' in pkg for pkg in packages):
            fieldnames.append('search_strategy')
        
        if append and os.path.exists(filename):
            # 追加模式：读取现有数据，去重，然后重写
            existing_packages = []
            try:
                with open(filename, 'r', newline='', encoding='utf-8') as csvfile:
                    reader = csv.DictReader(csvfile)
                    existing_packages = list(reader)
            except Exception as e:
                logger.warning(f"读取现有文件失败: {e}")
                existing_packages = []
            
            # 合并并去重
            all_packages = existing_packages + packages
            seen = set()
            unique_packages = []
            for pkg in all_packages:
                # 使用repository + package_name作为唯一标识
                key = f"{pkg.get('repository', '')}_{pkg.get('package_name', '')}"
                if key not in seen:
                    seen.add(key)
                    unique_packages.append(pkg)
            
            # 重写文件
            with open(filename, 'w', newline='', encoding='utf-8') as csvfile:
                writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
                writer.writeheader()
                writer.writerows(unique_packages)
            
            new_count = len(unique_packages) - len(existing_packages)
            logger.info(f"💾 实时保存: 新增 {new_count} 个包到 {filename} (总计 {len(unique_packages)} 个)")
        else:
            # 新建文件
            mode = 'a' if append else 'w'
            write_header = not append or not os.path.exists(filename)
            
            with open(filename, mode, newline='', encoding='utf-8') as csvfile:
                writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
                if write_header:
                    writer.writeheader()
                writer.writerows(packages)
            
            if append:
                logger.info(f"💾 实时保存: 新增 {len(packages)} 个包到 {filename}")
            else:
                logger.info(f"结果已保存到 {filename} (按星数排序，共 {len(packages)} 个包)")
        
        # 显示统计信息（仅在非追加模式下）
        if not append and packages:
            top_package = packages[0]
            logger.info(f"最高星数: {top_package.get('stars', 0)} ({top_package.get('repository', '')})")
            logger.info(f"  - 语言: {top_package.get('language', 'Unknown')}")
            logger.info(f"  - Fork数: {top_package.get('forks', 0)}")
            logger.info(f"  - 许可证: {top_package.get('license', 'Unknown')}")
            
            # 统计语言分布
            languages = {}
            for pkg in packages:
                lang = pkg.get('language', 'Unknown')
                languages[lang] = languages.get(lang, 0) + 1
            
            logger.info("语言分布:")
            for lang, count in sorted(languages.items(), key=lambda x: x[1], reverse=True)[:5]:
                logger.info(f"  - {lang}: {count} 个包")
    
    def save_repositories_to_csv(self, filename: str, append: bool = False):
        """
        将所有检查过的仓库保存到CSV文件
        
        Args:
            filename: 输出文件名
            append: 是否追加模式（用于实时保存）
        """
        repositories = self.progress_manager.get_checked_repositories()
        
        if not repositories:
            if not append:
                logger.warning("没有仓库信息可保存")
            return
        
        # 按星数降序排序
        repositories.sort(key=lambda x: x.get('stars', 0), reverse=True)
        
        fieldnames = [
            'repository', 'repository_url', 'stars', 'forks', 'language',
            'created_at', 'updated_at', 'description', 'license', 'topics',
            'open_issues', 'linux_support', 'has_packages', 'package_types', 'package_count'
        ]
        
        # 如果仓库中包含search_strategy字段，添加到fieldnames
        if repositories and any('search_strategy' in repo for repo in repositories):
            fieldnames.append('search_strategy')
        
        if append and os.path.exists(filename):
            # 追加模式：读取现有数据，去重，然后重写
            existing_repositories = []
            try:
                with open(filename, 'r', newline='', encoding='utf-8') as csvfile:
                    reader = csv.DictReader(csvfile)
                    existing_repositories = list(reader)
            except Exception as e:
                logger.warning(f"读取现有文件失败: {e}")
                existing_repositories = []
            
            # 合并并去重
            all_repositories = existing_repositories + repositories
            seen = set()
            unique_repositories = []
            for repo in all_repositories:
                # 使用repository作为唯一标识
                key = repo.get('repository', '')
                if key not in seen:
                    seen.add(key)
                    unique_repositories.append(repo)
            
            # 重写文件
            with open(filename, 'w', newline='', encoding='utf-8') as csvfile:
                writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
                writer.writeheader()
                writer.writerows(unique_repositories)
            
            new_count = len(unique_repositories) - len(existing_repositories)
            logger.info(f"💾 实时保存: 新增 {new_count} 个仓库到 {filename} (总计 {len(unique_repositories)} 个)")
        else:
            # 新建文件
            mode = 'a' if append else 'w'
            write_header = not append or not os.path.exists(filename)
            
            with open(filename, mode, newline='', encoding='utf-8') as csvfile:
                writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
                if write_header:
                    writer.writeheader()
                writer.writerows(repositories)
            
            if append:
                logger.info(f"💾 实时保存: 新增 {len(repositories)} 个仓库到 {filename}")
            else:
                logger.info(f"仓库信息已保存到 {filename} (按星数排序，共 {len(repositories)} 个仓库)")
        
        # 统计信息（仅在非追加模式下）
        if not append:
            linux_support_count = sum(1 for r in repositories if r.get('linux_support', False))
            has_packages_count = sum(1 for r in repositories if r.get('has_packages', False))
            
            logger.info(f"统计信息:")
            logger.info(f"  - 支持Linux: {linux_support_count} 个")
            logger.info(f"  - 有包: {has_packages_count} 个")
            logger.info(f"  - 无包: {len(repositories) - has_packages_count} 个")
    
    def run_search(self, max_repos_per_type: int = 30, use_new_strategy: bool = True, use_comprehensive: bool = False, topics: List[str] = None):
        """
        运行完整的搜索流程
        
        Args:
            max_repos_per_type: 每种类型最大搜索仓库数量
            use_new_strategy: 是否使用新的搜索策略（推荐）
            use_comprehensive: 是否使用全面搜索策略（遍历更多仓库）
            topics: 按主题搜索的主题列表
        """
        logger.info("开始GitHub软件包搜索...")
        
        if topics:
            logger.info(f"🎯 使用主题搜索策略：{topics}")
            
            # 使用主题搜索策略
            topic_packages = self.search_linux_packages_by_topic(topics, max_repos_per_type)
            
            # 按包类型分别保存
            deb_packages = [p for p in topic_packages if p.get('package_type') == 'deb']
            appimage_packages = [p for p in topic_packages if p.get('package_type') == 'appimage']
            tar_packages = [p for p in topic_packages if p.get('package_type') == 'tar']
            
            self.save_to_csv(deb_packages, f'github_deb_packages_topic_{"_".join(topics[:3])}.csv')
            self.save_to_csv(appimage_packages, f'github_appimage_packages_topic_{"_".join(topics[:3])}.csv')
            self.save_to_csv(tar_packages, f'github_linux_tar_packages_topic_{"_".join(topics[:3])}.csv')
            self.save_to_csv(topic_packages, f'github_all_packages_topic_{"_".join(topics[:3])}.csv')
            self.save_repositories_to_csv(f'github_checked_repositories_topic_{"_".join(topics[:3])}.csv')
            
            logger.info(f"主题搜索完成！总共找到 {len(topic_packages)} 个Linux软件包")
            logger.info("结果文件:")
            logger.info(f"- github_deb_packages_topic_{'_'.join(topics[:3])}.csv: deb包")
            logger.info(f"- github_appimage_packages_topic_{'_'.join(topics[:3])}.csv: appimage包")
            logger.info(f"- github_linux_tar_packages_topic_{'_'.join(topics[:3])}.csv: linux tar包")
            logger.info(f"- github_all_packages_topic_{'_'.join(topics[:3])}.csv: 所有包")
            logger.info(f"- github_checked_repositories_topic_{'_'.join(topics[:3])}.csv: 所有检查过的仓库")
            
        elif use_comprehensive:
            logger.info("🌍 使用全面搜索策略：多策略遍历GitHub仓库")
            
            # 使用全面搜索策略
            comprehensive_packages = self.search_linux_packages_comprehensive(max_repos_per_type)
            
            # 按包类型分别保存
            deb_packages = [p for p in comprehensive_packages if p.get('package_type') == 'deb']
            appimage_packages = [p for p in comprehensive_packages if p.get('package_type') == 'appimage']
            tar_packages = [p for p in comprehensive_packages if p.get('package_type') == 'tar']
            
            self.save_to_csv(deb_packages, 'github_deb_packages_comprehensive.csv')
            self.save_to_csv(appimage_packages, 'github_appimage_packages_comprehensive.csv')
            self.save_to_csv(tar_packages, 'github_linux_tar_packages_comprehensive.csv')
            self.save_to_csv(comprehensive_packages, 'github_all_packages_comprehensive.csv')
            self.save_repositories_to_csv('github_checked_repositories_comprehensive.csv')
            
            logger.info(f"全面搜索完成！总共找到 {len(comprehensive_packages)} 个Linux软件包")
            logger.info("结果文件:")
            logger.info("- github_deb_packages_comprehensive.csv: deb包")
            logger.info("- github_appimage_packages_comprehensive.csv: appimage包")
            logger.info("- github_linux_tar_packages_comprehensive.csv: linux tar包")
            logger.info("- github_all_packages_comprehensive.csv: 所有包")
            logger.info("- github_checked_repositories_comprehensive.csv: 所有检查过的仓库")
            
        elif use_new_strategy:
            logger.info("🚀 使用新搜索策略：先检查Linux支持，再按优先级检查包类型")
            
            # 使用新的统一搜索策略
            linux_packages = self.search_linux_packages(max_repos_per_type)
            
            # 按包类型分别保存
            deb_packages = [p for p in linux_packages if p.get('package_type') == 'deb']
            appimage_packages = [p for p in linux_packages if p.get('package_type') == 'appimage']
            tar_packages = [p for p in linux_packages if p.get('package_type') == 'tar']
            
            self.save_to_csv(deb_packages, 'github_deb_packages.csv')
            self.save_to_csv(appimage_packages, 'github_appimage_packages.csv')
            self.save_to_csv(tar_packages, 'github_linux_tar_packages.csv')
            self.save_to_csv(linux_packages, 'github_all_packages.csv')
            self.save_repositories_to_csv('github_checked_repositories.csv')
            
            logger.info(f"搜索完成！总共找到 {len(linux_packages)} 个Linux软件包")
            logger.info("结果文件:")
            logger.info("- github_deb_packages.csv: deb包")
            logger.info("- github_appimage_packages.csv: appimage包")
            logger.info("- github_linux_tar_packages.csv: linux tar包")
            logger.info("- github_all_packages.csv: 所有包")
            logger.info("- github_checked_repositories.csv: 所有检查过的仓库")
            
        else:
            logger.info("🔄 使用传统搜索策略：分别搜索三种包类型")
            
            all_packages = []
            
            # 搜索deb包
            deb_packages = self.search_deb_packages(max_repos_per_type)
            all_packages.extend(deb_packages)
            self.save_to_csv(deb_packages, 'github_deb_packages.csv')
            
            # 搜索appimage包
            appimage_packages = self.search_appimage_packages(max_repos_per_type)
            all_packages.extend(appimage_packages)
            self.save_to_csv(appimage_packages, 'github_appimage_packages.csv')
            
            # 搜索linux tar包
            tar_packages = self.search_linux_tar_packages(max_repos_per_type)
            all_packages.extend(tar_packages)
            self.save_to_csv(tar_packages, 'github_linux_tar_packages.csv')
            
            # 保存所有结果
            self.save_to_csv(all_packages, 'github_all_packages.csv')
            self.save_repositories_to_csv('github_checked_repositories.csv')
            
            logger.info(f"搜索完成！总共找到 {len(all_packages)} 个软件包")
            logger.info("结果文件:")
            logger.info("- github_deb_packages.csv: deb包")
            logger.info("- github_appimage_packages.csv: appimage包")
            logger.info("- github_linux_tar_packages.csv: linux tar包")
            logger.info("- github_all_packages.csv: 所有包")
            logger.info("- github_checked_repositories.csv: 所有检查过的仓库")

def main():
    """主函数"""
    parser = argparse.ArgumentParser(description='GitHub软件包检索工具')
    parser.add_argument('--max-repos', type=int, default=30, 
                       help='每种类型最大搜索仓库数量 (默认: 30)')
    parser.add_argument('--clear-progress', action='store_true',
                       help='清除之前的进度，重新开始')
    parser.add_argument('--progress-file', type=str, default='search_progress.pkl',
                       help='进度文件路径 (默认: search_progress.pkl)')
    parser.add_argument('--token', type=str, 
                       help='GitHub API token (也可通过环境变量 GITHUB_TOKEN 设置)')
    parser.add_argument('--old-strategy', action='store_true',
                       help='使用传统搜索策略（分别搜索三种包类型）')
    parser.add_argument('--comprehensive', action='store_true',
                       help='使用全面搜索策略（多策略遍历GitHub仓库）')
    parser.add_argument('--topics', nargs='+', 
                       help='按主题搜索，可以指定多个主题，例如: --topics desktop gui editor')
    
    args = parser.parse_args()
    
    print("GitHub软件包检索工具")
    print("=" * 50)
    
    # 获取GitHub token
    github_token = args.token or os.getenv('GITHUB_TOKEN') or os.getenv('GITHUB_PAT')
    
    if github_token:
        print("✅ 使用GitHub Token，API限制: 5000次/小时")
    else:
        print("⚠️  未使用GitHub Token，API限制: 60次/小时")
        print("💡 提示: 设置环境变量 GITHUB_TOKEN 或使用 --token 参数可提高API限制")
        print("   例如: export GITHUB_TOKEN=your_token_here")
        print("   或者: python github_package_finder.py --token your_token_here")
        print()
    
    # 创建查找器
    finder = GitHubPackageFinder(github_token, args.progress_file)
    
    # 清除进度（如果指定）
    if args.clear_progress:
        finder.progress_manager.clear_progress()
        print("🗑️ 进度已清除，重新开始搜索")
    
    # 运行搜索
    use_new_strategy = not args.old_strategy and not args.comprehensive and not args.topics
    use_comprehensive = args.comprehensive
    use_topics = args.topics is not None
    
    finder.run_search(
        max_repos_per_type=args.max_repos, 
        use_new_strategy=use_new_strategy, 
        use_comprehensive=use_comprehensive,
        topics=args.topics
    )

if __name__ == "__main__":
    main()
